﻿/* libstdf -- library for reading writing and manipulating STDF files and data.
   Copyright (C) 2009 Tushar Jog
   
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General
   Public License along with this library; if not, write to the
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301 USA 
*/

using System;
using System.Collections.Generic;

using U1 = System.Byte;
using U2 = System.UInt16;
using I1 = System.SByte;
using I2 = System.Int16;
using U4 = System.UInt32;
using I4 = System.Int32;
using R4 = System.Single;
using R8 = System.Double;
//using C1 = System.SByte;
using C1 = System.Char;
using B1 = System.Byte;
using N1 = System.Byte;

namespace stdf
{
    public class Pair<T, U> {
        public Pair() {
        }

        public Pair(T first, U second) {
            this.First = first;
            this.Second = second;
        }

        public T First { get; set; }
        public U Second { get; set; }
    };
	
	public enum ByteOrder {
		NotDefined   = 0,
		BigEndian    = 4321,
		LittleEndian = 1234,
		PDPEndian    = 3412
	};
	
	public enum RecordType
    {
        Header=0,
        FAR=10, ATR=20,
        MIR=110, MRR=120, PCR=130, HBR=140, SBR=150, PMR=160, PGR=162, PLR=163, RDR=170, SDR=180,
        WIR=210, WRR=220, WCR=230,
        PIR=510, PRR=520,
        TSR=1030,
        PTR=1510, MPR=1515, FTR=1520,
        BPS=2010, EPS=2020,
        GDR=5010, DTR=5030,
        Reserved=9999
    };
	
	public enum RWMode { None, ReadOnly, WriteOnly = 2 };
	

	/// <summary>
	/// Description of MyClass.
	/// </summary>
	public class CN
	{
		public CN() {
			_str = "";
		}
		public U2 getLength() {
			return (U2) (_str.Length + 1);
		}
		public void set(string s) {
			if(s.Length < 256)
				_str = s;
		}
		public bool isValid() { 
			if(_str.Length == 0) 
				return false; 
			else 
				return true; 
		}
		public string str() { return _str; }
		public string ToString() { return _str; }
		
		protected string _str;
	}
	
	public class DN {
		public DN() {
			count = 0;
            data = new List<U1>();
		}
		public U2 getLength() {
			U2 numBytes = 0;
			numBytes += (U2) ((count / 8) + 1);
			if((count % 8) == 0)
				numBytes--;
			
			numBytes += 2;
			
			return numBytes;
		}
        public U2 getCount() { return count; }
        private void set(ref U2 newCount, ref List<U1> newData) {
            count = newCount;
            data = newData;
        }
        public void set( ref List<U1> newData) {
            if(newData.Count < 65536) {
                data = newData;
                count = (U2) data.Count;
            }
        }
        public U2 getNumBytes() {
            U2 numBytes = (U2) ((count / 8) + 1);
			if((count % 8) == 0)
				numBytes--;
            return numBytes;
        }
		public U2       count;
		public List<U1> data;
	}

    public class BN {
        public BN() {
            count = 0;
            data = new List<U1>();
        }
        public U2 getLength() {
            U2 len = (U2) (1 + count);
            return len;
        }
		public void set(ref List<U1> newData) {
			if(newData.Count < 256) {
				data = newData;
				count = (U1) data.Count;
			}
		}

        public U1       count;
        public List<U1> data;
    }

    public class VN {
        public VN() {
            code = 255;
            r8 = 0;
            u4 = 0;
            cn = new CN();
        }

        public U2 getLength() {
            U2 len = 1; // code byte
            switch (code)
            {
                case  0: len += 0;              break; // B0
                case  1: len += 1;              break; // U1
                case  2: len += 2;              break; // U2
                case  3: len += 4;              break; // U4
                case  4: len += 1;              break; // I1
                case  5: len += 2;              break; // I2
                case  6: len += 4;              break; // I4
                case  7: len += 4;              break; // R4
                case  8: len += 8;              break; // R8
                case 10: len += cn.getLength(); break; // CN
                case 11: len += bn.getLength(); break; // BN
                case 12: len += dn.getLength(); break; // CN
                case 13: len += 1; break; // N1
                default:
                    break;
            }
            switch(code) {
                case  0: len += 0; break;
                case  1: len += 1; break;
                default: break;
            }

            return len;
        }
        public U1 code;

        public U1 u1;
        public U2 u2;
        public U4 u4;
        public I1 i1;
        public I2 i2;
        public I4 i4;
        public R4 r4;
        public R8 r8;
        public N1 n1;
        public CN cn;
        public BN bn;
        public DN dn;
    }
}
